package com.rabbiter.hospital.controller;

import com.rabbiter.hospital.pojo.Doctor;
import com.rabbiter.hospital.service.DoctorService;
import com.rabbiter.hospital.service.OrderService;
import com.rabbiter.hospital.service.PatientService;
import com.rabbiter.hospital.utils.JwtUtil;
import com.rabbiter.hospital.utils.ResponseData;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("doctor")
public class DoctorController {
    @Autowired
    private DoctorService doctorService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private PatientService patientService;

    /**
     * 登录数据验证
     * 通过接收医生ID和密码参数，验证医生的登录信息
     * 如果验证成功，将返回一个包含医生信息和JWT令牌的Map
     * 如果验证失败，将返回一个包含错误信息的ResponseData对象
     * @param dId       医生ID，用于识别医生
     * @param dPassword 医生输入的密码
     * @return 包含医生信息和登录结果的ResponseData对象
     */
    @RequestMapping(value = "login", method = RequestMethod.POST)
    @ResponseBody
    public ResponseData login(@RequestParam(value = "dId") int dId, @RequestParam(value = "dPassword") String dPassword) {
        // 调用doctorService中的登录方法，尝试获取Doctor对象
        Doctor doctor = this.doctorService.login(dId, dPassword);
        if (doctor != null) {
            // 如果登录成功，创建一个Map来存储医生信息和JWT令牌
            Map<String, String> map = new HashMap<>();
            // 将医生姓名放入Map
            map.put("dName", doctor.getdName());
            // 将医生ID放入Map，需要转换为String类型
            map.put("dId", String.valueOf(doctor.getdId()));
            // 使用JwtUtil生成JWT令牌，并将其放入Map
            String token = JwtUtil.getToken(map);
            map.put("token", token);
            // 返回登录成功的结果，包含医生信息和JWT令牌
            return ResponseData.success("登录成功", map);
        } else {
            // 如果登录失败，返回登录失败的结果，包含错误信息
            return ResponseData.fail("登录失败，密码或账号错误");
        }
    }

    /**
     * 查看当天挂号列表
     * 该方法通过接收医生ID和开始时间参数，来查询当天未确认的挂号订单
     * 主要用于展示当天医生需要接诊的患者列表
     * @param dId    医生的ID，用于识别特定的医生
     * @param oStart 挂号开始时间，用于确定当天的挂号记录
     * @return 返回一个ResponseData对象，包含当天的挂号信息
     */
    @RequestMapping("findOrderByNull")
    public ResponseData findOrderByNull(@Param(value = "dId") int dId, @RequestParam(value = "oStart") String oStart) {
        System.out.println("账号时间为" + dId + oStart);
        return ResponseData.success("返回当天挂号信息成功", this.orderService.findOrderByNull(dId, oStart));
    }

    /**
     * 根据患者id查询患者信息
     * 通过此方法，系统能够根据提供的患者ID检索并返回相应的患者信息
     * 使用了RequestMapping注解来映射URL路径中的"findPatientById"到此方法
     * @param pId 患者ID，用于标识要查询的患者
     * @return 返回一个ResponseData对象，包含操作结果和患者信息
     */
    @RequestMapping("findPatientById")
    public ResponseData findPatientById(int pId) {
        // 返回一个成功响应，包含患者信息
        return ResponseData.success("返回患者信息成功！", this.patientService.findPatientById(pId));
    }

    /**
     * 分页根据科室查询所有医生信息
     * 通过此接口可以实现根据科室分页查询医生信息的功能
     * 参数包括页码、每页大小、查询关键词、排班日期和科室名称
     * @param pageNumber  当前页码，用于分页查询
     * @param size        每页显示的记录数，用于分页查询
     * @param query       查询关键词，用于模糊匹配医生信息
     * @param arrangeDate 排班日期，用于筛选医生的排班情况
     * @param dSection    科室名称，用于根据科室查询医生
     * @return 返回分页查询医生信息的结果，包括总记录数、当前页码、每页记录数和医生信息列表
     */
    @RequestMapping("findDoctorBySectionPage")
    public ResponseData findDoctorBySectionPage(int pageNumber, int size, String query, String arrangeDate, String dSection) {
        // 调用doctorService中的findDoctorBySectionPage方法查询医生信息，并返回结果
        return ResponseData.success("分页根据科室查询所有医生信息成功", this.doctorService.findDoctorBySectionPage(pageNumber, size, query, arrangeDate, dSection));
    }

    /**
     * 用户评价
     * 该方法用于更新医生的星级评价
     * @param dId   医生的ID
     * @param dStar 用户给医生的星级评价（1-5）
     * @return 返回评价操作的结果，成功或失败
     */
    @RequestMapping("updateStar")
    public ResponseData updateStar(int dId, Double dStar) {
        if (this.doctorService.updateStar(dId, dStar)) return ResponseData.success("评价成功");
        return ResponseData.fail("评价失败");
    }

    /**
     * 上传Excel导入数据
     * 该方法用于处理通过POST请求上传的Excel文件，旨在批量导入数据
     * @param multipartFile 含有Excel文件的MultipartFile对象，用于文件上传
     * @return ResponseData对象，包含操作结果和相应消息
     * @throws Exception 如果处理过程中发生任何异常，将抛出异常
     */
    @RequestMapping(value = "uploadExcel", method = RequestMethod.POST)
    @ResponseBody
    public ResponseData uploadExcel(@RequestParam("file") MultipartFile multipartFile) throws Exception {
        // 调用doctorService的uploadExcel方法进行Excel数据上传，判断上传是否成功
        if (this.doctorService.uploadExcel(multipartFile)) return ResponseData.success("上传Excel导入数据成功");
        else return ResponseData.fail("上传Excel导入数据失败");
    }

    /**
     * Excel导出数据
     * 通过HttpServletResponse响应流来导出数据到Excel文件中
     * @param response HttpServletResponse对象，用于构建HTTP响应
     * @return 如果数据成功导出到Excel，返回成功消息；否则返回失败消息
     * @throws IOException 如果在构建HTTP响应过程中发生I/O错误
     */
    @RequestMapping("downloadExcel")
    public ResponseData downloadExcel(HttpServletResponse response) throws IOException {
        // 调用doctorService中的downloadExcel方法尝试导出数据到Excel
        if (this.doctorService.downloadExcel(response)) return ResponseData.success("Excel导出数据成功");
        return ResponseData.fail("Excel导出数据失败");
    }


}
